package c1;

/**
 * 虚假唤醒测试
 * 生产者消费者
 * 当判断条件是if的时候，就会发生负数的情况，应当改成while循环
 * 消费者B: 货物不足！
 * 消费者A: 货物不足！
 * 生产者B: 1
 * 消费者A: 0
 * 消费者A: 货物不足！
 * 消费者B: -1
 * 消费者B: 货物不足！
 * 消费者A: -2
 * 消费者B: -3
 * 生产者A: -2
 * 生产者B: -1
 * 生产者A: 0
 */
public class SpuriousWakeupTest {
    public static void main(String[] args) {
        Clerk clerk = new Clerk();
        Producer producer = new Producer(clerk);
        Customer customer = new Customer(clerk);

        new Thread(producer, "生产者A").start();
        new Thread(customer, "消费者A").start();
        new Thread(producer, "生产者B").start();
        new Thread(customer, "消费者B").start();
    }
}

// 售货员
class Clerk {
    private int product = 0;

    // 进货
    public synchronized void get() {
        // 产品已满
        //while(product >= 1){
        if (product >= 1) {
            System.out.println(Thread.currentThread().getName() + ": " + "已满！");
            try {
                this.wait();
            } catch (InterruptedException e) {
            }
        }
        // 该线程从while中出来的时候，是满足条件的
        System.out.println(Thread.currentThread().getName() + ": " + ++product);
        this.notifyAll();
    }

    // 卖货
    public synchronized void sale() {
        if (product <= 0) {
            System.out.println(Thread.currentThread().getName() + ": " + "货物不足！");
            try {
                this.wait();
            } catch (InterruptedException e) {
            }
        }

        System.out.println(Thread.currentThread().getName() + ": " + --product);
        this.notifyAll();
    }
}

// 生产者
class Producer implements Runnable {
    private Clerk clerk;

    public Producer(Clerk clerk) {
        this.clerk = clerk;
    }

    // 进货
    @Override
    public void run() {
        for (int i = 0; i < 2; ++i) {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
            }
            clerk.get();
        }
    }
}

// 消费者
class Customer implements Runnable {
    private Clerk clerk;

    public Customer(Clerk clerk) {
        this.clerk = clerk;
    }

    // 卖货
    @Override
    public void run() {
        for (int i = 0; i < 2; ++i) {
            clerk.sale();
        }
    }
}
